/**
 * =============================================================
 * 【后端服务器主文件】
 * 主要功能：设置Express服务器、处理HTTP请求、管理WebSocket连接
 * =============================================================
 */

/*******************************
 * 1. 依赖和模块引入
 *******************************/
const express = require('express');
const http = require('http');
const bodyParser = require("body-parser");
const cors = require("cors");
const jwt = require("jsonwebtoken");
const url = require("url");
const socketIo = require("socket.io");
const mysql = require('mysql2');

/*******************************
 * 2. 应用和服务器初始化
 *******************************/
const app = express();
const server = http.createServer(app);
const port = 8888;

// Socket.IO 服务器实例化
const io = socketIo(server, {
  cors: {
    origin: '*',
    methods: ['GET', 'POST']
  }
});

/*******************************
 * 3. 数据库连接配置
 *******************************/
const db = mysql.createConnection({
  user: 'root',
  password: 'root123',
  host: 'localhost',
  database: 'chat_test'
});

// 数据库连接
db.connect(err => {
  if (err) {
    console.error('数据库连接失败:', err.message);
  } else {
    console.log('数据库连接成功');
  }
});

/*******************************
 * 4. 中间件配置
 *******************************/
app.use(cors()); // 跨域支持
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(express.json());

// 全局响应头设置
app.all('*', (req, res, next) => {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Headers', 'Content-Type');
  res.header('Access-Control-Allow-Methods', '*');
  res.header('Content-Type', 'application/json;charset=utf-8');
  next();
});
/*******************************
 * 5. WebSocket 实时通信处理
 *******************************/
// 存储用户ID与Socket连接的映射
const userSockets = new Map();

io.on('connection', (socket) => {
  console.log('新客户端连接:', socket.id);

  // 获取前端传递的用户ID
  const userId = socket.handshake.query.userId;

  // 1. 用户ID验证
  if (!userId) {
    console.log('无效连接: 未提供用户ID');
    socket.disconnect(true); // 强制断开无效连接
    return;
  }

  // 2. 处理已有连接
  if (userSockets.has(userId)) {
    console.log(`用户 ${userId} 已有连接, 正在关闭旧连接`);
    const oldSocket = userSockets.get(userId);
    oldSocket.disconnect();
  }

  // 3. 存储新连接
  console.log(`用户 ${userId} 已连接, 映射到socket ID: ${socket.id}`);
  userSockets.set(userId, socket);

  // 4. 连接成功的确认
  socket.emit('connection_success', {
    message: 'WebSocket连接成功',
    userId,
    socketId: socket.id,
    timestamp: Date.now()
  });
  //实时通信发送消息
  socket.on('send-message', (message) => {
    console.log('收到发送消息请求:', message);

    // 1. 存储到数据库
    const insertSql = `
    INSERT INTO char_table 
    (sendid, receiveid, info, status, created_at) 
    VALUES (?, ?, ?, 0, NOW())
  `;

    db.query(insertSql, [
      message.sendid,
      message.receiveid,
      message.info
    ], (err, result) => {
      if (err) {
        console.error('保存消息失败:', err);

        // 通知发送方失败
        socket.emit('message-error', {
          message: '消息发送失败',
          originalMessage: message,
          error: err.message
        });
        return;
      }

      console.log('消息保存成功，ID:', result.insertId);

      // 2. 广播给接收方
      const newMessage = {
        ...message,
        id: result.insertId.toString(),
        created_at: new Date().toISOString()
      };

      // 3. 检查接收方是否在线
      const receiverSocket = userSockets.get(message.receiveid);
      receiverSocket.emit('new-message', newMessage);
      console.log(`消息已实时发送给 ${message.receiveid}`);

      // if (userSockets.has(message.receiveid)) {
      //   
      //   
      // } else {
      //   console.log(`接收方 ${message.receiveid} 不在线，消息已存储`);
      // }

      // 4. 回发给发送方确认
      socket.emit('message-sent', {
        ...newMessage,
        status: 1 // 已送达
      });
    });
  });
  // 5. 断开连接处理
  socket.on('disconnect', () => {
    console.log(`用户 ${userId} 断开连接`);
    userSockets.delete(userId);
  });

  // 6. 错误处理
  socket.on('error', (err) => {
    console.error(`用户 ${userId} 连接错误:`, err.message);
  });
});
/*******************************
 * 6. HTTP路由定义
 *******************************/

// 根路由 - 服务状态检查
app.get('/', (req, res) => {
  res.send("服务器运行正常");
});

// 用户注册接口
app.post("/register", (req, res) => {
  const { id, registerName, firstPassword, secondPassword } = req.body;

  // 参数验证
  if (!registerName || !firstPassword || !secondPassword) {
    return res.send({ code: 0, msg: "用户名与密码为必传参数" });
  }

  // 密码一致性验证
  if (firstPassword !== secondPassword) {
    return res.send({ code: 0, msg: "两次密码必须相同" });
  }

  // 用户名重复检查
  const registerSql = `SELECT * FROM users_table WHERE username = '${registerName}'`;
  db.query(registerSql, (err, result) => {
    if (err) throw err;

    // 用户名已存在处理
    if (result.length >= 1) {
      res.send({ code: 0, msg: "注册失败，用户名重复" });
    } else {
      // 创建新用户
      const sqlStr = "INSERT INTO users_table(id, username, password) VALUES(?, ?, ?)";
      db.query(sqlStr, [id, registerName, firstPassword], (err, result) => {
        if (err) throw err;
        res.send({
          code: result.affectedRows === 1 ? 200 : 0,
          msg: result.affectedRows === 1 ? "注册成功" : "注册失败"
        });
      });
    }
  });
});

// 用户登录接口
app.post("/login", (req, res) => {
  const { username, password } = req.body;
  // 参数验证
  if (!username || !password) {
    return res.send({ code: 0, msg: "用户名与密码为必传参数" });
  }
  // 用户查询
  const sqlStr = "SELECT * FROM users_table WHERE username = ?";
  db.query(sqlStr, [username], (err, result) => {
    if (err) throw err;

    // 用户不存在处理
    if (result.length == 0) {
      return res.send({ code: 0, msg: "用户名不存在" });
    }

    // 密码验证
    if (password !== result[0].password) {
      return res.send({ code: 0, msg: "密码错误" });
    }

    // 生成JWT令牌
    const token = jwt.sign(
      { username: result[0].username },
      "secret",
      { expiresIn: "24h" }
    );

    // 登录成功响应
    res.send({
      code: 200,
      msg: "登录成功",
      token,
      data: result[0].id
    });
  });
});

// 用户搜索接口
app.get("/search", (req, res) => {
  const { searchIfom: ifom } = url.parse(req.url, true).query;

  // 搜索词验证
  if (!ifom) {
    return res.send({ code: 0, msg: "请输入要搜索的用户名" });
  }

  // 执行搜索查询
  const searchSql = `SELECT * FROM users_table WHERE username LIKE '${ifom}%'`;
  db.query(searchSql, (err, results) => {
    if (err) throw err;

    // 搜索结果处理
    if (results.length == 0) {
      res.send({ code: 0, msg: "用户名不存在" });
    } else {
      res.send({ code: 200, msg: "搜索用户名成功", data: results });
    }
  });
});

// 添加好友接口
app.post("/addUser", (req, res) => {
  const { id: userId, friendId, verifyInfo } = req.body;

  // 验证是否已是好友
  const reVerifySql = "SELECT * FROM friends_table WHERE userId=? AND friendId=?";
  db.query(reVerifySql, [userId, friendId], (err, result) => {
    if (err) throw err;

    // 关系状态判断
    if (result.length === 1) {
      const status = result[0].status;
      const msg = status === 1 ?
        "添加好友失败，对方已经是你的好友了！" :
        "已发送过添加好友请求，请耐心等待对方响应！";
      return res.send({ code: 0, msg });
    }

    // 添加好友请求
    const addSql = "INSERT INTO friends_table(userid, friendid, verifyinfo, status) VALUES(?, ?, ?, 0)";
    db.query(addSql, [userId, friendId, verifyInfo], (err, result) => {
      if (err) throw err;

      // 发送请求响应
      res.send({
        code: result.affectedRows === 1 ? 200 : 0,
        msg: result.affectedRows === 1 ?
          "添加好友消息发送成功！" : "添加好友消息发送失败！"
      });
    });
  });
});

//获取好友列表接口
app.get("/getfriends", (req, res) => {
  const { userid: userId } = req.query;
  const getRelationsSql = `
    SELECT DISTINCT
      CASE
        WHEN userid = ? THEN friendid
        ELSE userid
      END AS friend_id
    FROM friends_table
    WHERE status = 1
      AND (userid = ? OR friendid = ?);
  `;

  db.query(getRelationsSql, [userId, userId, userId], (err, relations) => {
    if (err) {
      console.error('查询好友关系错误:', err);
      return res.status(500).json({ code: 500, msg: '数据库错误' });
    }
    // 如果没有好友
    if (relations.length === 0) {
      return res.json({ code: 200, data: [], msg: "没有好友记录" });
    }
    const friendIds = relations.map(r => r.friend_id);

    const getUserNamesSql = `
      SELECT id, username
      FROM users_table
      WHERE id IN (?);
    `;

    db.query(getUserNamesSql, [friendIds], (err, users) => {
      if (err) {
        console.error('查询好友信息错误:', err);
        return res.status(500).json({ code: 500, msg: '数据库错误' });
      }

      // 只返回ID和用户名
      const friendList = users.map(user => ({
        friendId: user.id,
        friendName: user.username
      }));
      // console.log('准备推送给前端的好友列表：', JSON.stringify(friendList, null, 2));
      res.json({
        code: 200,
        data: friendList,
        msg: "获取好友列表成功！"
      });
    });
  });
});
//获取聊过天的聊天列表
app.get("/getfriendschat", (req, res) => {
  // 1. 获取查询参数
  const userId = req.query.userId;
  // 2. 验证必要参数
  if (!userId) {
    return res.status(400).json({
      code: 400,
      message: '缺少必要的参数: userId'
    });
  }

  // 3. 创建SQL查询语句
  const query = `
    SELECT 
      partner.id AS friendId,
      partner.username AS friendName,
      MAX(msg.created_at) AS lastMessageTime
    FROM (
      SELECT 
        CASE 
          WHEN sendid = ? THEN receiveid 
          ELSE sendid 
        END AS partner_id
      FROM char_table
      WHERE sendid = ? OR receiveid = ?
      GROUP BY partner_id
    ) partners
    JOIN users_table partner ON partner.id = partners.partner_id
    LEFT JOIN char_table msg ON (
      (msg.sendid = ? AND msg.receiveid = partners.partner_id) OR 
      (msg.receiveid = ? AND msg.sendid = partners.partner_id)
    )
    GROUP BY partner.id, partner.username
    ORDER BY lastMessageTime DESC;
  `;

  // 4. 执行查询
  db.query(
    query,
    [userId, userId, userId, userId, userId],
    (error, results, fields) => {
      // 5. 处理查询错误
      if (error) {
        console.error('数据库查询失败:', error);
        return res.status(500).json({
          code: 500,
          message: '数据库查询失败',
          error: error.message
        });
      }

      // 6. 处理空结果集
      if (!results || results.length === 0) {
        return res.json({
          code: 200,
          message: '没有聊天记录',
          data: { sessions: [] }
        });
      }

      // 7. 转换结果格式
      const sessions = results.map(row => ({
        friendId: row.friendId,
        friendName: row.friendName,
        lastMessageTime: row.lastMessageTime ? new Date(row.lastMessageTime).getTime() : 0,
        unreadCount: 0,
        isActive: false
      }));
      // console.log('准备推送给前端的好友列表：', JSON.stringify(sessions));
      // 8. 返回成功响应
      res.json({
        code: 200,
        message: '获取聊天好友成功',
        data: {
          sessions
        }
      });
    }
  );
});
//获取历史消息
app.get('/getHistoryMessages', (req, res) => {
  const { userId, friendId } = req.query;
  // 验证参数是否存在
  if (!userId || !friendId) {
    return res.status(400).json({ code: 400, msg: '参数缺失' });
  }
  // 查询消息
  const getMessagesSql = `SELECT id, sendid, receiveid, info, created_at, status
        FROM char_table
        WHERE (sendid = ? AND receiveid = ?) OR (sendid = ? AND receiveid = ?)
        ORDER BY created_at ASC`;
  db.query(getMessagesSql, [userId, friendId, friendId, userId], (err, messages) => {
    if (err) {
      console.error(err);
      return res.status(500).json({ code: 500, msg: '获取消息失败' });
    }
    console.log(messages);

    res.json({
      code: 200,
      msg: '成功',
      data: messages
    });
  });
});

// 获取用户信息接口
app.get("/getid", (req, res) => {
  const { id: userId } = url.parse(req.url, true).query;

  // 查询用户信息
  const getDataSql = `SELECT * FROM users_table WHERE id = '${userId}'`;
  db.query(getDataSql, (err, result) => {
    if (err) throw err;
    res.send({ code: 200, data: result, msg: "获取用户信息成功！" });
  });
});

// 获取聊天记录接口
app.get("/getinfo", (req, res) => {
  const sendid = url.parse(req.url, true).query.sendId;
  const receiveid = url.parse(req.url, true).query.receiveId;

  // 查询双方聊天记录
  const getDataSql = `SELECT * FROM char_table 
    WHERE (sendId = '${sendid}' AND receiveId='${receiveid}') 
    OR (sendId = '${receiveid}' AND receiveId='${sendid}') 
    ORDER BY id DESC LIMIT 8`;

  db.query(getDataSql, (err, result) => {
    if (err) throw err;
    res.send({ code: 200, data: result, msg: "获取聊天记录成功！" });
  });
});

/*******************************
 * 7. 错误处理中间件
 *******************************/
app.use((err, req, res, next) => {
  console.error('服务器错误:', err.message);
  res.status(err.status || 500).send({ code: 500, msg: "服务器内部错误" });
});

/*******************************
 * 8. 服务器启动
 *******************************/
server.on('error', (err) => {
  console.error('服务器启动失败:', err.message);
});

server.on('listening', () => {
  console.log(`服务器已启动，运行在 http://192.168.237.130:${port}`);
  console.log(`实时服务地址: ws://localhost:${port}`);
});

server.listen(port);